package client;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import org.apache.commons.codec.binary.Base64;


public class MonControleur{
	private MonModele jeSuisTonModele;
	static MaVue client;
	int BUFFER_SIZE = 4096;
	
	private String maGrosseCommande;
	private InputStream input;
	private Socket sock1;
	private int numConn;
	private long fileLength;
	private BufferedReader in;
	private FileInputStream fis;
	private JOptionPane erreur = new JOptionPane();
	private ImageIcon error = new ImageIcon(getClass().getResource("/error2.jpg"));
	private int nbAttrClasse=-1, nbAttrDoc=-1;
	
	
/**************************** Constructeur MonControleur ********************************/
	MonControleur(){
		jeSuisTonModele = new MonModele();
	}

	
	
/**************************** Methode MonControleur *************************************/
	//Vérification que l'utilisateur existe + récupération de l'UID + lancement de la nouvelle Vue
	public void connexion(String serveur, String user){
		jeSuisTonModele.getUser().setName(user);
		jeSuisTonModele.setMonGrosServeur(serveur);
		String usernameRecu, userUidRecu;
		
		getUserAutorisation();
		
		if(!jeSuisTonModele.getUser().getUid().equals("0") && !jeSuisTonModele.getUser().getName().isEmpty()){
			client.dispose();
			if(jeSuisTonModele.getUser().getUid().equals("U1")){
				client.maNouvelleVueAdmin();
				//client = new MaVue(jeSuisTonModele.getUser(), jeSuisTonModele.getUser().getUid());
				System.out.println("Voici mon Uid2 : " +jeSuisTonModele.getUser().getUid());
			}
			else{
				client.maNouvelleVueClient();
				System.out.println("Voici mon Uid2 : " +jeSuisTonModele.getUser().getUid());
			}
		}
		//si l'utilisateur n'existe pas
		else
			jeSuisTonModele.getUser().setUid("0");
		
	}

	//Récupérer le vector de Doc et Classe de tous les utilisateurs (Admin)
	public void initEstConnecteAdmin(String user){
		Vector resuDoc = new Vector();
		Vector resuClasse = new Vector();
		
		//récupération des Vector doc et classe (de tous les utilisateurs)
		
		
		
		
		//modification du modele + MAJ du modele de la vue
		jeSuisTonModele.setDoc(resuDoc);
		jeSuisTonModele.setClasse(resuClasse);
		client.setMonModele(jeSuisTonModele);
		
	}
	
	//Récupérer le vector de Doc et Classe de l'utilisateur client
	public void initEstConnecteClient(String user){
		Vector resuDoc = new Vector();
		Vector resuClasse = new Vector();
		
		//récupération des Vector doc et classe
		
		//modification du modele + MAJ du modele de la vue
		jeSuisTonModele.setDoc(resuDoc);
		jeSuisTonModele.setClasse(resuClasse);
		client.setMonModele(jeSuisTonModele);
		
	}
	
	

	
	//Récupère les infos d'un document
	public Vector getInfoDoc(String nomDoc){
		Vector docCourant = new Vector();
		docCourant = getCaractDoc(nomDoc);
		return docCourant;
		
	}
	
	//Récupère les infos d'une classe
	public Vector getInfoClasse(String nomClasse){
		Vector classeCourante = new Vector();
		classeCourante = getCaractClasse(nomClasse);
		return classeCourante;
	}
	
	
/*********************** TELECHARGEMENT de Fichier ************************/
	public void monTelechargementFichier(String filename){
		String path = ChoixFichierTelecharger(filename);

		if(path!=null)
			getDoc(filename, path);
		
	}
	
	public void copierDoc(String oldDoc, String filename, String classe, Vector attr){
		String path = "C:\\temp\\"+filename;
		getDoc(oldDoc, path);
		addFile(path+filename, filename, classe, attr);
	}
	
	
  	public static String ChoixFichierTelecharger(String myFile) {
		JFileChooser choix = new JFileChooser();
		File f = new File(myFile);
		choix.setSelectedFile(f);
		String file=null;
		try{
			int i = choix.showSaveDialog(null);
			file = choix.getSelectedFile().getAbsolutePath();
		    if(i == JFileChooser.CANCEL_OPTION)
		    	file=null;
		}catch(Exception e){
		}
		
		return file;
	}

  	
/********************* ENVOI de Fichier 
 * @param classe ************************************/
	public void monEnvoiFichier(String classe, Vector attr){
		JFileChooser monFichier = ChoixFichierEnvoyer();
		String fichier = monFichier.getSelectedFile().getName();
		String filepath = monFichier.getSelectedFile().getAbsolutePath();
		System.out.println("My PATH :" +filepath);
		if(fichier!=null){
			addFile(filepath, fichier, classe, attr);
			//envoi le fichier au serveur
			
		}
	}
	

/********************** Fenetre de choix de fichier *************************/
  	public static JFileChooser ChoixFichierEnvoyer() {
		JFileChooser choix = new JFileChooser();
		String file=null;
		try{
			choix.showOpenDialog(null);
			if(!choix.getSelectedFile().getAbsolutePath().isEmpty())
				file = choix.getSelectedFile().getAbsolutePath();		
		}catch(Exception e){
			file=null;
		}
		
		return choix;
	}
	
	
	
	//ferme la vue du client, redémarre le client.
	public void deconnexion(){
		jeSuisTonModele = new MonModele();
		client.setMonModele(jeSuisTonModele);
		client = new MaVue();
	}
	
	



/**************************** COMMANDES GET ************************************/
	public void getUserAutorisation(){
		//String s = "GET /accessGed%20get%20-user%20"+user+"\n";
		maGrosseCommande= "GET /accessGed%20get%20-user%20"+jeSuisTonModele.getUser().getName()+"\n";
		 try
		    {
		     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
		                                new OutputStreamWriter(
		                                    server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		      bw.flush();
		      
		      	String line= in.readLine();
		      	while (line != null)
		        {
		      		jeSuisTonModele.getUser().setUid(line);
		      		System.out.println(line);
		          line = in.readLine();

		        }
		      	client.setMonModele(jeSuisTonModele);
				bw.close();
				server.close();
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		      System.out.println("Unable to write to output stream");
		    }  
		 System.out.println("Voici mon Uid : " +jeSuisTonModele.getUser().getUid());
		 System.out.println("Voici mon Uid : " +client.getMonModele().getUser().getUid());
		 maGrosseCommande = null;
		  }
		   

//Commande pour recuperer un document nous appartenant	
	public void getDoc(String filename, String myPath){
		maGrosseCommande= "GET /accessGed%20get%20-uid%20"+client.getMonModele().getUser().getUid()+"%20-doc%20"+filename+"\n";
		 try
		    {
		     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
		                                new OutputStreamWriter(
		                                    server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		      bw.flush();
		      
		      	String line= in.readLine();
		      	while (line != null)
		        {
		      		System.out.println(line);
		      		base64DecodetoFile(myPath, line);
		          line = in.readLine();
		          
		        }
				//System.out.println(requete);
				bw.close();
				server.close();
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		      System.out.println("Unable to write to output stream");
		    }  

		 maGrosseCommande = null;
		
		
	}

	
//Commande pour obtenir les caracteristiques d'un document
	public Vector getCaractDoc(String doc){
			Vector temp = new Vector();
			nbAttrDoc=-1;
			maGrosseCommande= "GET /accessGed%20get%20-uid%20"+client.getMonModele().getUser().getUid()+"%20-attr%20-doc%20"+doc+"\n";
			System.out.println("getCaractDoc : " + maGrosseCommande);
			 try
			    {
			     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
				 BufferedWriter bw = new BufferedWriter(
			                                new OutputStreamWriter(
			                                    server.getOutputStream()));
				 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
				 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
			      bw.flush();
			      int i=0;
			      	String line= in.readLine();
			      	while (line != null)
			      	{
			      		if(i>3){
			      			nbAttrDoc++;
			      			temp.add(line);
				      		System.out.println(line+" Il y a "+nbAttrDoc+" attributs");
			      		
			      		}
			          line = in.readLine();
			          i++;
			        }
					bw.close();
					server.close();
			    }
			    catch(Exception e)
			    {
			    	e.printStackTrace();
			      System.out.println("Unable to get attributs");
			    }  

			 maGrosseCommande = null;
			 return temp;
		}

		
//Commande pour obtenir les caracteristiques d'une classe
	public Vector getCaractClasse(String classe){
		Vector temp = new Vector();
		nbAttrClasse=-1;
		maGrosseCommande= "GET /accessGed%20get%20-uid%20"+client.getMonModele().getUser().getUid()+"%20-attr%20-classe%20"+classe+"\n";
		System.out.println("getCaractClasse : " + client.getMonModele().getUser().getUid());
		try
		    {
		     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
		                                new OutputStreamWriter(
		                                    server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		      bw.flush();
		      int i=0;
		      
		      	String line= in.readLine();
		      	while (line != null)
		      	{
		      		if(i>3){
		      		temp.add(line);
		      		nbAttrClasse++;
		      		System.out.println(line+" Il y a "+nbAttrClasse+" attributs");
		      		}
		          line = in.readLine();
		          i++;
		        }
				bw.close();
				server.close();
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		      System.out.println("Unable to get attributs");
		    }  

		 maGrosseCommande = null;
		 return temp;
	}
		
	
//Commande pour lister mes documents
	public Vector listeAllDoc(){
		Vector temp = new Vector();
		maGrosseCommande= "GET /accessGed%20get%20-uid%20"
							+client.getMonModele().getUser().getUid()+
							"%20-list%20doc\n";
		System.out.println("Ma grosse commande : "+maGrosseCommande);
		try
		    {
		     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
		                                new OutputStreamWriter(
		                                    server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		      bw.flush();
		      int i=0;
		      
		      	String line= in.readLine();
		      	while (line != null)
		        {
		      		if(i>3){
		      		temp.add(line);
		      		System.out.println(line);
		      		}
		          line = in.readLine();
		          i++;
		        }
		      	jeSuisTonModele.setDoc(temp);
		      	client.setMonModele(jeSuisTonModele);
				//System.out.println(requete);
				bw.close();
				server.close();
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		      System.out.println("Unable to get all doc");
		    }  
		 maGrosseCommande = null;
		 return temp;
	}

	
//Commande pour lister mes documents
	public Vector listeAllClasse(){
			Vector temp = new Vector();
			maGrosseCommande= "GET /accessGed%20get%20-uid%20"
								+client.getMonModele().getUser().getUid()+
								"%20-list%20classe\n";
			 try
			    {
			     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
				 BufferedWriter bw = new BufferedWriter(
			                                new OutputStreamWriter(
			                                    server.getOutputStream()));
				 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
				 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
			      bw.flush();
			      int i=0;
			      
			      	String line= in.readLine();
			      	while (line != null)
			        {
			      		if(i>3){
				      		temp.add(line);
				      		System.out.println(line);
			      		}
			          line = in.readLine();
			          i++;
			        }
					//System.out.println(requete);
					bw.close();
					server.close();
			    }
			    catch(Exception e)
			    {
			    	e.printStackTrace();
			      System.out.println("Unable to get all doc");
			    }  
			 maGrosseCommande = null;
			 return temp;
		}
	

	
	public Vector listeAllUsers() {
		Vector temp = new Vector();
		maGrosseCommande= "GET /accessGed%20get%20-uid%20"
							+client.getMonModele().getUser().getUid()+
							"%20-list%20users\n";
		 try
		    {
		     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
		                                new OutputStreamWriter(
		                                    server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		      bw.flush();
		      int i=0;
		      
		      	String line= in.readLine();
		      	while (line != null)
		        {
		      		if(i>3){
			      		temp.add(line);
			      		System.out.println(line);
		      		}
		          line = in.readLine();
		          i++;
		        }
				//System.out.println(requete);
				bw.close();
				server.close();
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		      System.out.println("Unable to get all doc");
		    }  
		 maGrosseCommande = null;
		 return temp;
	}
	
	
/***************************** COMMANDE DELETE ******************************************/
		
//Supprimer un document
	public void supprimerDoc(String filename){
			maGrosseCommande= "GET /accessGed%20del%20-uid%20"+client.getMonModele().getUser().getUid()+
									"%20-doc%20"+filename+"\n";
			try
			{
			 Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
			                            new OutputStreamWriter(
			                                server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
			  bw.flush();
			  
			  	String line= in.readLine();
			  	while (line != null)
			    {
			  		System.out.println(line);
			      line = in.readLine();
			    }
				//System.out.println(requete);
				bw.close();
				server.close();
			}
			catch(Exception e)
			{
				e.printStackTrace();
			  System.out.println("Unable to delete doc");
			}  
			maGrosseCommande = null;
		}	
	
//Supprimer une classe
	public void supprimerClasse(String classe){
			maGrosseCommande= "GET /accessGed%20del%20-uid%20"+client.getMonModele().getUser().getUid()+
									"%20-classe%20"+classe+"\n";
			try
			{
			 Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
			                            new OutputStreamWriter(
			                                server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
			  bw.flush();
			  
			  	String line= in.readLine();
			  	while (line != null)
			    {
			  		System.out.println(line);
			      line = in.readLine();
			    }
				//System.out.println(requete);
				bw.close();
				server.close();
			}
			catch(Exception e)
			{
				e.printStackTrace();
			  System.out.println("Unable to delete classe");
			}  
			maGrosseCommande = null;
		}	
	
	
/***************************** Gestion Utilisateur **************************************/

//Ajouter un utilisateur
	public void ajoutUtilisateur(String newUserName){
		maGrosseCommande= "GET /accessGed%20add%20-uid%20"+client.getMonModele().getUser().getUid()+
								"%20-user%20"+newUserName+"\n";
		try
		{
		 Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
		 BufferedWriter bw = new BufferedWriter(
		                            new OutputStreamWriter(
		                                server.getOutputStream()));
		 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
		 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		  bw.flush();
		  
		  	String line= in.readLine();
		  	while (line != null)
		    {
		  		System.out.println(line);
		      line = in.readLine();
		    }
			//System.out.println(requete);
			bw.close();
			server.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		  System.out.println("Unable to get all doc");
		}  
		jeSuisTonModele.addUser(newUserName);
		client.setMonModele(jeSuisTonModele);
		maGrosseCommande = null;
	}
	
//Supprimer un utilisateur
	public void supprimerUtilisateur(String UserName){
			maGrosseCommande= "GET /accessGed%20del%20-uid%20"+client.getMonModele().getUser().getUid()+
									"%20-user%20"+UserName+"\n";
			try
			{
			 Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
			                            new OutputStreamWriter(
			                                server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
			  bw.flush();
			  
			  	String line= in.readLine();
			  	while (line != null)
			    {
			  		System.out.println(line);
			      line = in.readLine();
			    }
				//System.out.println(requete);
				bw.close();
				server.close();
			}
			catch(Exception e)
			{
				e.printStackTrace();
			  System.out.println("Unable to delete user");
			}  
			maGrosseCommande = null;
		}	

	
	

/*********************** AUTRES ********************************/
	
//Commande pour chercher si un fichier existe et ou il se trouve
	public void getSearch(String filename){
		
	}

/****************************** COMMANDE ADD *********************************************/
//Ajouter (transfert) d'un document sur le serveur
	public void addFile(String filepath, String filename, String classe, Vector attrV){
		String attr=null;
		//System.out.println("My PATH AD FILE :" +filepath);
		maGrosseCommande= "GET /accessGed%20add%20-uid%20"+client.getMonModele().getUser().getUid()+
						"%20-classe%20"+classe+"%20-doc%20"+filename+"%20"+base64EncodeFile(filepath);
		for(int i=0; i<attrV.size();i++){
			if(i==0)
				attr="%20-attr%20";
			else
				attr+="%20-attr%20";
			attr+=attrV.get(i);
		}
		maGrosseCommande=maGrosseCommande+attr;
		maGrosseCommande+="\n";
		System.out.println("ma Commande : "+maGrosseCommande);
		 try
		    {
		     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
		                                new OutputStreamWriter(
		                                    server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		      bw.flush();
		      
		      	String line= in.readLine();
		      	while (line != null)
		        {
		      		System.out.println(line);
		          line = in.readLine();
		          
		        }
				bw.close();
				server.close();
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		      System.out.println("Unable to get attributs");
		    }  
		 maGrosseCommande = null;
	}
	
//Ajouter une classesur le serveur
	public void addClasse(String nomClasse, Vector type, Vector a, int nb){
		String attr="%20";
		maGrosseCommande= "GET /accessGed%20add%20-uid%20"+client.getMonModele().getUser().getUid()+
						"%20-classe%20"+nomClasse;
		System.out.println("add classe : "+maGrosseCommande);
		for(int i=0; i<nb;i++){
			if(i==0)
				attr+="-type%20";
			else
				attr+="%20-type%20";
			attr+=type.get(i);
			attr+="%20-attr%20";
			attr+=a.get(i);
		}
		maGrosseCommande=maGrosseCommande+attr;
		maGrosseCommande+="\n";
		System.out.println("add classe : "+maGrosseCommande);
		 try
		    {
		     Socket server     = new Socket(client.getMonModele().getMonGrosServeur(),80); 
			 BufferedWriter bw = new BufferedWriter(
		                                new OutputStreamWriter(
		                                    server.getOutputStream()));
			 in = new BufferedReader ( new InputStreamReader(server.getInputStream())); 
			 bw.write(maGrosseCommande, 0, maGrosseCommande.length());
		      bw.flush();
		      
		      	String line= in.readLine();
		      	while (line != null)
		        {
		      		System.out.println(line);
		          line = in.readLine();
		          
		        }
				//System.out.println(requete);
				bw.close();
				server.close();
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		      System.out.println("Unable to get attributs");
		    }  
		 maGrosseCommande = null;
	}


/****************************** CODE/DECODE Base 64 **********************************/
	protected String base64EncodeFile(String url){
		StringBuffer sb = new StringBuffer();
		byte[]  temp;
		try {
		
		BufferedInputStream input = new BufferedInputStream(new FileInputStream(url));
			
			  byte[] buf = new byte[3000000];
	
			  while (true) {
			   int len = input.read(buf);
			   System.out.println("passageici " +len);
			   if (len == -1){
				   input.close();
				   System.out.println(sb.toString());
				   return sb.toString();}
			   temp= new byte[len];
			   for(int i=0;i<len;i++)
				   temp[i]= buf[i];
			   sb.append(Base64.encodeBase64String(temp));
			  
			  }
		
		
		} catch (Exception e) {
			System.out.println(" Erreur: le Fichier "+url+" n'a pu être sauvegardé. ");
			e.printStackTrace();
			return null;
		}
	}
	
	public boolean base64DecodetoFile(String nomFichier, String chaineB64){
		if (nomFichier==null |chaineB64==null )return false;
		Base64 b64 =new Base64();
		byte[]temp;
		try{
		OutputStream output = new FileOutputStream(nomFichier);
		temp =b64.decode(chaineB64);	
		for(int i=0;i<temp.length;i++){
		    output.write(temp[i]);
		}		
		output.close();
		return true;}
		
		catch(Exception e){
			System.out.println(" Erreur: le Fichier "+nomFichier+" n'a pu être restauré. ");
			e.printStackTrace();
			return false;
		}
		
	}


	
public static void main(String[] args){

	client = new MaVue();
}


}
	
	
